Getting started
###############

Genode can be approached from two different angles: as an operating-system
architecture or as a practical tool kit. This chapter assists you with
exploring Genode as the latter. After introducing the recommended
development environment,
it guides you through the steps needed to obtain the source code
(Section [Obtaining the source code]), to use the tool chain
(Section [Using the build system]), to test-drive system scenarios
(Section [A simple system scenario]), and to create your first custom
component from scratch (Section [Hello world]).


Recommended development environment
-----------------------------------

Genode is regularly used and developed on GNU/Linux. It is recommended to
use the latest long-term support (LTS) version of Ubuntu. Make sure that your
installation satisfies the following requirements:

* GNU Make version 3.81 (or newer) needed by the build system,
* _libSDL-dev_ needed to run system scenarios directly on Linux,
* _tclsh_ and _expect_ needed by test-automation and work-flow tools,
* _xmllint_ for validating configurations,
* _qemu_, _xorriso_, _sgdisk_, and _e2tools_ needed for running
  system scenarios on non-Linux platforms via the Qemu emulator.

For using the entire collection of ported 3rd-party software, the following
packages should be installed additionally:
_byacc_, _autoconf2.64_, _autogen_, _bison_, _flex_, _g++_, _git_, _gperf_,
_libxml2-utils_, _subversion_, and _xsltproc_.


Seeking help
------------

The best way to get assistance while exploring Genode is to consult the
mailing list, which is the primary communication medium of regular
users and developers alike. Please feel welcome to join in!

:Mailing Lists:

  [https://genode.org/community/mailing-lists]

If you encounter a new bug, ambiguous documentation, or a missing feature,
please consider opening a corresponding issue at the issue tracker:

:Issue tracker:

  [https://github.com/genodelabs/genode/issues]


Obtaining the source code
=========================

The centerpiece of Genode is the source code found within the official Git
repository:

:Source code at GitHub:

  [https://github.com/genodelabs/genode]

To obtain the source code, clone the Git repository:

! git clone https://github.com/genodelabs/genode.git

After cloning, you can find the source code within
the _genode/_ directory. In the following, we refer to this directory
as _<genode-dir>_.


Source-tree structure
=====================

Top-level directory
-------------------

At the root of the directory tree, there is the following content:

:_doc/_: Documentation in plain text format, including the
  release notes
  of all versions. _Practical hint:_ The comprehensive release notes
  conserve most of the hands-on documentation aggregated over the lifetime
  of the project. When curious about a certain topic, it is often worthwhile to
  "grep" for the topic within the release notes to get a starting point
  for investigation.

:_tool/_: Tools and scripts to support the build system, various boot loaders,
  the tool chain, and the management of 3rd-party source code. Please find
  more information in the _README_ file contained in the subdirectory.

:_repos/_: The so-called source-code repositories, which contain the actual
  source code of the framework components. The source code is not organized
  within a single source tree but multiple trees. Each tree is called a
  _source-code repository_ and has the same principle structure.
  At build time, a set of source-code repositories can be selected to be
  incorporated into the build process. Thereby, the source-code repositories
  provide a coarse-grained modularization of the framework.


Repositories overview
---------------------

The _<genode-dir>/repos/_ directory contains the following source-code
repositories.

:_base/_:

  The fundamental framework interfaces as well as the platform-agnostic parts
  of the core component (Section [Core - the root of the component tree]).

:_base-<platform>/_:
  Platform-specific supplements of the _base/_ repository where _<platform>_
  corresponds to one of the following:

  :_linux_:

    Linux kernel (both x86_32 and x86_64).

  :_nova_:

    NOVA microhypervisor.
    More information about the NOVA platform is provided by Section
    [Execution on the NOVA microhypervisor (base-nova)].

  :_hw_:

    The hw platform allows the execution of Genode on bare hardware
    without the need for a separate kernel. The kernel functionality is
    included in the core component. It supports the 32-bit ARM, 64-bit ARM,
    64-bit x86, and 64-bit RISC-V CPU architectures.
    The hw platform is also used as the basis for executing Genode on top of
    the Muen separation kernel. More information about the hw platform can be
    found in Section [Execution on bare hardware (base-hw)].

  :_sel4_:

    The seL4 microkernel developed by NICTA in Sydney. The support for this
    kernel is highly experimental.

  :_foc_:

    Fiasco.OC is a modernized version of the L4/Fiasco microkernel with a
    completely revised kernel interface fostering capability-based
    security.

  :_okl4_:

    OKL4 kernel originally developed at Open-Kernel-Labs.

  :_pistachio_:

    L4ka::Pistachio kernel developed at University of Karlsruhe.

  :_fiasco_:

    L4/Fiasco kernel originally developed at Technische Universität Dresden.

:_os/_:

  OS components such as the init component, device drivers, and basic system
  services.

:_demo/_:

  Various services and applications used for demonstration purposes, for
  example the graphical application launcher and the tutorial browser
  described in Section [A simple system scenario] can be found here.

:_hello_tutorial/_:

  Tutorial for creating a simple client-server scenario. This
  repository includes documentation and the complete source code.

:_libports/_:

  Ports of popular open-source libraries, most importantly the C library.
  Among the 3rd-party libraries are Qt5, libSDL, freetype, Python, ncurses,
  Mesa, and libav.

:_dde_linux/_:

  Device-driver environment for executing Linux kernel subsystems as
  user-level components. Among the subsystems are the USB stack, the
  Intel wireless stack, and the TCP/IP stack.

:_dde_ipxe/_:

  Device-driver environment for executing network drivers of the iPXE project.

:_dde_bsd/_:

  Device-driver environment for audio drivers ported from OpenBSD.

:_dde_rump/_:

  Port of rump kernels, which are used to execute subsystems of the NetBSD
  kernel as user-level components.
  The repository contains a server that uses a rump kernel to provide
  various NetBSD file systems.

:_ports/_:

  Ports of 3rd-party applications.

:_gems/_:

  Components that use
  both native Genode interfaces as well as features of other high-level
  repositories, in particular shared libraries provided by _libports/_.


Using the build system
======================

Genode relies on a custom tool chain, which can be downloaded at the following
website:

:Tool chain:

  [https://genode.org/download/tool-chain]


Build directory
---------------

The build system never touches the source tree but generates object
files, libraries, and programs in a dedicated build directory. We do not have a
build directory yet. For a quick start, let us create one using the following
command:

! cd <genode-dir>
! ./tool/create_builddir x86_64

_To follow the subsequent steps of test driving the Linux version of Genode,_
_the specified platform argument should match your host OS installation. If_
_you are using a 32-bit installation, specify 'x86_32' instead of 'x86_64'._

The command creates a new build directory at 'build/x86_64'.


Build configuration
-------------------

Before using the build directory, it is recommended to revisit and
possibly adjust the build configuration, which is located in the
_etc/_ subdirectory of the build directory, e.g., _build/x86_64/etc/_.
The _build.conf_ file contains global build parameters, in particular
the selection of source-code repositories to be incorporated, the kernel
to use ('KERNEL'), and the targeted board ('BOARD'). It is also
a suitable place for adding global build options. For example, for
enabling GNU make to use 4 CPU cores, use the following line in the
_build.conf_ file:

! MAKE += -j4


Building components
-------------------

The recipe for building a component has the form of a _target.mk_ file
within the _src/_ directory of one of the source-code repositories.
For example, the _target.mk_ file of the init component is located
at _<genode-dir>/repos/os/src/init/target.mk_. To build the component, execute
the following command from within the build directory:

! make init

The argument "init" refers to the path relative to the _src/_ subdirectory.
The build system determines and builds all targets found under this path in
all source-code repositories.
When the build the is finished, the resulting executable binary can be found
in a subdirectory that matches the target's path. Additionally, the build
system installs a symbolic link in the _bin/_ subdirectory that points to the
executable binary.

If the specified path contains multiple _target.mk_ files in different
subdirectories, the build system builds all of them. For example, the
following command builds all targets found within one of the
_<repo>/src/drivers/_ subdirectories:

! make drivers

Furthermore, it is possible to specify multiple targets at once. The following
command builds both the init component and the nitpicker GUI server component:

! make init server/nitpicker


A simple system scenario
========================

The build directory offers much more than an environment for building
components. It supports the automation of system-integration work flows,
which typically include the following steps:

# Building a set of components,
# Configuring the static part of a system scenario,
# Assembling a boot directory with all ingredients needed by the scenario,
# Creating a boot image that can be loaded onto the target platform,
# Booting the target platform with the boot image,
# Validating the behavior of the scenario.

The recipe for such a sequence of steps can be expressed in the form of
a so-called run script. Each run script represents a system scenario and
entails all information required to reproduce the scenario. Run scripts can
reside within the _run/_ subdirectory of any source-code repository.

Genode comes with a ready-to-use run script showcasing a simple graphical demo
scenario. The run script is located at _<genode-dir>/repos/os/run/demo.run_.
It leverages Genode's package-management tools for assembling a static system
image.
The package management is explained in detail in Section [Package management].
For now, we can skip the details by instructing the build system to
automatically create packages and update their version numbers for us.
Uncomment the following line in the _build/x86_64/build.conf_ file:

! RUN_OPT += --depot-auto-update

In contrast to the building of individual components as described in the
previous section, the integration of a complete system scenario requires us to
select a particular OS kernel to use. The following command instructs the
build system to build, integrate, and start the "run/demo" scenario on the
Linux kernel:

! make run/demo KERNEL=linux BOARD=linux

The command prompts the build system to lookup a run script called _demo.run_
in all repositories listed in _etc/build.conf_.
It will eventually find the run script within the _os/_ repository. After
completing the build of all components needed, the command will then
automatically start the scenario.
Because the build directory was created for the _x86_64_ platform and we
specified "linux" as 'KERNEL', the scenario will be executed directly on the
host system where each Genode component resides in a distinct Linux process.
To explore the scenario, follow the instructions given by the graphical
tutorial browser.

The terminal where the 'make run/demo' command was issued displays the log
output of the Genode system. To cancel the execution,
hit _control-c_ in the terminal.


Targeting a microkernel
-----------------------

Whereas the ability to run system scenarios on top of Linux allows for the
convenient and rapid development of components and protocols, Genode is
primarily designed for the use of microkernels. The choice of the microkernel
to use is up to the user of the framework and may depend on various factors
like the feature set, the supported hardware architectures, the license, or
the development community. To execute the demo scenario directly on the NOVA
microhypervisor, the following preparatory steps are needed:

# Download the 3rd-party source code of the NOVA microhypervisor
  ! <genode-dir>/tool/ports/prepare_port nova

  The _prepare_port_ tool downloads the source code of NOVA to a
  subdirectory at _<genode-dir>/contrib/nova-<hash>/_ where _<hash>_
  uniquely refers to the prepared version of NOVA.

# On real hardware, the scenario needs a framebuffer driver. The VESA
  driver relies on a 3rd-party x86-emulation library in order to execute
  the VESA BIOS code. Download the 3rd-party source code of the _x86emu_
  library:
  ! <genode-dir>/tool/ports/prepare_port x86emu

  The source code will be downloaded to _<genode-dir>/contrib/x86emu-<hash>/_.

# To boot the scenario as an operating system on a PC, a boot loader is
  needed. The build process produces a bootable disk or ISO image
  that includes the GRUB2 boot loader as well as a working boot-loader
  configuration. Download the boot loader as ingredient for the image-creation
  step.

  ! <genode-dir>/tool/ports/prepare_port grub2

# Since NOVA supports the x86_64 architecture of our build directory, we
  can keep using the existing build directory that we just used for Linux.
  However, apart from enabling the parallelization of the build process as
  mentioned in Section [Using the build system], we need to incorporate
  the _libports_ source-code repository into the build process by uncommenting
  the corresponding line in the configuration. Otherwise the build system
  would fail to build the VESA driver, which resides within _libports/_.

With those preparations in place, issue the execution of the demo run
script from within the build directory:

! make run/demo KERNEL=nova BOARD=pc

This time, an instance of Qemu will be started to execute the demo scenario.
The Qemu command-line arguments appear in the log output. As suggested
by the arguments, the scenario is supplied to Qemu as an ISO image residing
at _var/run/demo.iso_. This ISO image can not only be used with Qemu but
also with a real machine. For example, creating a bootable USB stick with
the system scenario is as simple as writing the ISO image onto an USB stick:
! sudo dd if=var/run/demo.iso of=/dev/<usb-device> bs=8M conv=fsync

Note that _<usb-device>_ refers to the device node of an USB stick. It can be
determined using the 'dmesg' command after plugging-in the USB stick.
For booting from the USB stick, you may need to adjust the BIOS
settings of the test machine accordingly.


Hello world
===========

This section introduces the steps needed to create and execute a simple
custom component that prints a hello-world message.


Using a custom source-code repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In principle, it would be possible to add a new component to one of the
existing source-code repositories found at _<genode-dir>/repos/_. However,
unless the component is meant to be incorporated into upstream development
of the Genode project, it is generally recommended to keep custom code
separate from Genode's code base. This eases future updates to new versions
of Genode and allows you to pick a revision-control system of your choice.

The new repository must appear within the _<genode-dir>/repos/_ directory.
This can be achieved by either hosting it as a subdirectory or by creating
a symbolic link that points to an arbitrary location of your choice. For
now, let us host a new source-code repository called "lab" directly within
the _repos/_ directory.

! cd <genode-dir>
! mkdir repos/lab

The lab repository will contain the source code and build rules for a
single component as well as a run script for executing the component within
Genode. Component source code reside in a _src/_ subdirectory. By convention,
the _src/_ directory contains further subdirectories for hosting different
types of components, in particular _server_ (services and protocol stacks),
_drivers_ (hardware-device drivers), and _app_ (applications). For the
hello-world component, an appropriate location would be _src/app/hello/_:

! mkdir -p repos/lab/src/app/hello


Source code and build description
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The _hello/_ directory contains both the source code and the build description
of the component. The main part of each component typically resides in a
file called _main.cc_. Hence, for a hello-world program, we have to create
the _repos/lab/src/app/hello/main.cc_ file with the following content:

! #include <base/component.h>
! #include <base/log.h>
!
! void Component::construct(Genode::Env &)
! {
!   Genode::log("Hello world");
! }

The _base/component.h_ header contains the interface each component must
implement.
The 'construct' function is called by the component's execution environment
to initialize the component. The interface to the execution environment is
passed as argument. This interface allows the application code to interact
with the outside world. The simple example above merely produces a log
message. The 'log' function is defined in the _base/log.h_ header.

The component does not exit after the 'construct' function returns. Instead,
it becomes ready to respond to requests or signals originating from other
components. The example above does not interact with other components though.
Hence, it will just keep waiting infinitely.

Please note that there exists a recommended coding style for genuine Genode
components. If you consider submitting your work to the upstream development
of the project, please pay attention to these common guidelines.

:Coding-style guidelines:

  https://genode.org/documentation/developer-resources/coding_style

The source file _main.cc_ is accompanied by a build-description file called
_target.mk_. It contains the declarations for the source files, the libraries
used by the component, and the name of the component. Create the file
_repos/lab/src/app/hello/target.mk_ with the following content:

! TARGET = hello
! SRC_CC = main.cc
! LIBS  += base


Building the component
~~~~~~~~~~~~~~~~~~~~~~

With the build-description file in place, it is time to build the new
component, for example from within the _x86_64_ build directory as
created in Section [A simple system scenario]. To aid the build system
to find the component, we have to extend the build
configuration _<build-dir>/etc/build.conf_ by appending the following line:

! REPOSITORIES += $(GENODE_DIR)/repos/lab

By adding this line, the build system will consider our custom source-code
repository. To build the component, issue the following command:

! make app/hello

This step compiles the _main.cc_
file and links the executable ELF binary called "hello". The result can be
found in the _<build-dir>/app/hello/_ subdirectory.


Defining a system scenario
~~~~~~~~~~~~~~~~~~~~~~~~~~

For testing the component, we need to define a system scenario that
incorporates the component. As mentioned in
Section [A simple system scenario], such a description has the form of
a run script. To equip the _lab_ repository with a run script, we first
need to create a _lab/run/_ subdirectory:

! mkdir <genode-dir>/repos/lab/run

Within this directory, we create the file
_<genode-dir>/repos/lab/run/hello.run_ with the following content:

!build "core init app/hello"
!create_boot_directory
!install_config {
! <config>
!   <parent-provides>
!     <service name="LOG"/>
!     <service name="PD"/>
!     <service name="CPU"/>
!     <service name="ROM"/>
!   </parent-provides>
!   <default-route>
!     <any-service> <parent/> </any-service>
!   </default-route>
!   <default caps="100"/>
!   <start name="hello">
!     <resource name="RAM" quantum="10M"/>
!   </start>
! </config>
!}
!build_boot_image "core ld.lib.so init hello"
!append qemu_args "-nographic -m 64"
!run_genode_until {Hello world.*\n} 10

This run script performs the following steps:

# It builds the components core, init, and app/hello.
; XXX references to the Sections about core and init

# It creates a fresh boot directory at _<build-dir>/var/run/hello_.
  This directory contains all files that will end up in the final
  boot image.

# It creates a configuration for the init component. The configuration
  starts the hello component as the only child of init. Session
  requests originating from the hello component will always be directed
  towards the parent of init, which is core. The '<default>' node declares
  that each component may consume up to 100 capabilities.

# It assembles a boot image with the executable ELF binaries core,
  ld.lib.so (the dynamic linker), init, and hello. The binaries are picked up
  from the _<build-dir>/bin/_ subdirectory.

# It instructs Qemu (if used) to disable the graphical output.

# It triggers the execution of the system scenario and watches the log
  output for the given regular expression. The execution ends when
  the log output appears or after a timeout of 10 seconds.

The run script can be executed from within the build directory via the
command:

! make run/hello KERNEL=linux BOARD=linux

After the boot output of the used kernel, the scenario will produce the
following output:

! [init -> test-printf] Hello world
!
! Run script execution successful.

The label within the brackets at the start of each line identifies the
component where the message originated from. The final line is printed by the
run tool after it successfully matched the log output against the regular
expression specified to the 'run_genode_until' command.


[raw spec/clearpage]

Responding to external events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Most non-trivial components respond to external events such as user input,
timer events, device interrupts, the arrival of new data, or RPC requests
issued by other components.

The following example presents the typical skeleton of such a component.
The 'construct' function merely creates an object representing the application
as a 'static' local variable. The actual component code lives inside the
'Main' class.

! #include <base/component.h>
! #include <base/log.h>
! #include <timer_session/connection.h>
!
! namespace Hello { struct Main; }
!
! struct Hello::Main
! {
!   Genode::Env &_env;
!
!   Timer::Connection _timer { _env };
!
!   void _handle_timeout()
!   {
!     log("woke up at ", _timer.elapsed_ms(), " ms");
!   }
!
!   Genode::Signal_handler<Main> _timeout_handler {
!     _env.ep(), *this, &Main::_handle_timeout };
!
!   Main(Genode::Env &env) : _env(env)
!   {
!     _timer.sigh(_timeout_handler);
!     _timer.trigger_periodic(1000*1000);
!     Genode::log("component constructed");
!   }
! };
!
! void Component::construct(Genode::Env &env)
! {
!   static Hello::Main main(env);
! }

First, note the 'Hello' namespace. As a good practice, component code
typically lives in a namespace. The component-specific namespace may
incorporate other namespaces - in particular the 'Genode' namespace - without
polluting the global scope.

The constructor of the 'Main' object takes the Genode environment as argument
and stores it as the reference member variable '_env'. The member variable is
prefixed with an underscore to highlight the fact that it is
private to the 'Main' class. In principle, 'Main' could be a 'class' with '_env'
being part of the 'private' section, but as 'Main' is the top-level class of
the component that is not accessed by any other parts of the program, we use a
'struct' for brevity while still maintaining the convention to prefix private
members with an underscore character. When spotting the use of such a prefixed
variable in the code, we immediately see that it is part of the code's object
context, not being an argument or a local variable.

By aggregating a 'Timer::Connection' as a member variable, the 'Main' object
requests a session to a timer service at construction time. As this session
request requires an interaction with the outside world, the '_env' needs to
be passed to the '_timer' constructor.

In order to respond to events from the timer, the 'Main' class hosts a
'_timeout_handler' object. Its constructor arguments refer to the object and
a method to be executed whenever an event occurs. The timeout handler object is
registered at the '_timer' as the recipient of timeout events via the 'sigh'
method. Finally, the timer is instructed to trigger timeout events at a rate
of 1 second.

The following remarks are worth noting:

* The programming style expresses what the component _is_ rather than what
  the component _does_.

* The component does not perform any dynamic memory allocation.

* When called, the '_handle_timeout' method has its context (the 'Main' object)
  readily available, which makes the application of internal state changes as
  response to external events very natural.

* Both the 'construct' function as well as the 'Main::_handle_timeout' method
  do not block for external events.

* The component does not receive any indication about the number of occurred
  events, just the fact that at least one event occurred. The
  '_handle_timeout' code explicitly requests the current time from the
  timer driver via the synchronous RPC call 'elapsed_ms'.

To execute the new version of the component, we need to slightly modify the
run script.

!build "core init timer app/hello"
!create_boot_directory
!install_config {
! <config>
!   <parent-provides>
!     <service name="LOG"/>
!     <service name="PD"/>
!     <service name="CPU"/>
!     <service name="ROM"/>
!   </parent-provides>
!   <default-route>
!     <any-service> <parent/> <any-child/> </any-service>
!   </default-route>
!   <default caps="100"/>
!   <start name="timer">
!     <resource name="RAM" quantum="1M"/>
!     <provides> <service name="Timer"/> </provides>
!   </start>
!   <start name="hello">
!     <resource name="RAM" quantum="10M"/>
!   </start>
! </config>
!}
!build_boot_image "core ld.lib.so init timer hello"
!append qemu_args "-nographic -m 64"
!run_genode_until forever

The modifications are as follows:

* Since the hello component now relies on a timer service, we need to
  build and integrate a timer driver into the scenario by extending
  the 'build' and 'build_boot_image' steps accordingly.

* We instruct init to spawn the timer driver as an additional component
  by adding a '<start>' node to init's configuration. Within this node,
  we declare that the component provides a service of type "Timer".

* To enable the hello component to open a "Timer" session at the timer
  driver, the default route is modified to consider any children as
  servers whenever the requested service is not provided by the parent.

* This time, we let the scenario run forever so that we can watch the
  messages printed at periodic intervals.

When starting the run script, we can observe the periodic activation
of the component in the log output:

![init] child "timer" announces service "Timer"
![init -> hello] component constructed
![init -> hello] woke up at 12 ms
![init -> hello] woke up at 1008 ms
![init -> hello] woke up at 2005 ms
!...


Next steps
==========

There are several possible ways to continue your exploration.

# To form a *mental model* of how Genode works, give Chapter [Architecture]
  a read. In particular, Sections [Capability-based security],
  [Recursive system structure], [Resource trading], and
  [Inter-component communication] deserve your attention.
  Section [Component composition] nicely complements this theoretic material
  with a number of illustrative examples.

# If you are eager to see Genode's *potential* *unfolded*, try out
  the Genode-based operating system called Sculpt OS, which is available
  as a downloadable system image along with thorough documentation.

  :Sculpt OS:

    [https://genode.org/download/sculpt]

# Genode comprises a *feature set* of hundreds of ready-to-use components,
  which are fun to discover and to combine. Most components are not only
  accompanied with documentation in the form of README files local to the
  respective source code, but come with at least one ready-to-use run script
  or test package, which illustrates the integration of the component in
  executable form. After familiarizing yourself with the concept of run
  scripts by reading Section [System integration and automated testing],
  review the _run/_ and _recipes/pkg/_ subdirectories of the various
  source-code repositories, for example those at _repos/os/run/_ or
  _repos/gems/run/_.

# To follow the work of the Genode *community*, learn about current lines of
  work, plans, and experiences, head to the Genodians.org community blog.

  :Genodians.org:

    [https://genodians.org]

